<template>
    <div id="container"></div>
</template>

<script setup>
import { LogicFlow, RectNode, RectNodeModel, HtmlNode, HtmlNodeModel } from "@logicflow/core";
import '@logicflow/core/dist/style/index.css';
import { DndPanel,Snapshot } from '@logicflow/extension';
import '@logicflow/extension/lib/style/index.css';
import { message } from "@/utils/message";
import { ref, onMounted, nextTick } from "vue";
import { getLfData, addLfData } from '@/api/ontologyConstruction'
import { lfDataJs } from './lfData';

const keyData = ref("");
const dataObj = ref("0");
const dataType = ref("0");
const time1 = ref("");
const time2 = ref("");
const dataMap = ref("");
const isShow = ref(0)
const fileName = ref("");

const edgeId = ref();
// const wrapperRef = ref();
onMounted(() => {
  createSvg();
  //getLfNodeData();
});

  // 创建画布
  const lf = ref();
  const nodeId = ref()
  const createSvg = () => {
    lf.value = new LogicFlow({
      container: document.querySelector('#container'),
      edgeType: 'bezier',
      plugins: [ DndPanel,Snapshot ],
      width: 600,
      height: 580,
      background: {
        backgroundColor: '#f2f3f5'
      },
      grid: false,
      style: {
          rect: {
            rx: 5,
            ry: 5,
            strokeWidth: 1,
            fill: '#c1c1c1',
            stroke: '#e5e7eb'
          },
          baseEdge: {
            stroke: "#0c78e1",
            strokeWidth: 2,
          },
      },
      adjustEdge: false,
      edgeSelectedOutline: true,
      edgeTextEdit: true
    })
    // const showCenterHeight = wrapperRef.value.getBoundingClientRect().height;
    // const showCenterWidth = wrapperRef.value.getBoundingClientRect().width;
    // lf.value.resize(showCenterWidth,showCenterHeight);
    const data = {
      nodes: [
        {
          id: 1,
          type: "htmlNode",
          x: 100,
          y: 50,
          text: {
            value: 'Headquarters'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },
        {
          id: 2,
          type: "htmlNode",
          x: 100,
          y: 150,
          text: {
            value: 'FACTORY'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },
        {
          id: 3,
          type: "htmlNode",
          x: 400,
          y: 50,
          text: {
            value: 'protocol'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },
        {
          id: 4,
          type: "htmlNode",
          x: 400,
          y: 150,
          text: {
            value: 'Headquaters'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },{
          id: 5,
          type: "htmlNode",
          x: 250,//200
          y: 270,
          text: {
            value: 'Decive'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },{
          id: 6,
          type: "htmlNode",
          x: 80,
          y: 390,
          text: {
            value: 'Headquaters'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },
        {
          id: 7,
          type: "htmlNode",
          x: 400,
          y: 390,
          text: {
            value: 'Headquaters'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },{
          id: 8,
          type: "htmlNode",
          x: 400,
          y: 480,
          text: {
            value: 'Data'
          },
          properties: {
            keyObj: '',
            keyClass: '',
            keyId: 'hello',
            keyData: ''
          },
        },
      ],
      edges: [
          {
            type: 'bezier',
            sourceNodeId: 2,
            targetNodeId:1,
        },
        {
            type: 'bezier',
            sourceNodeId: 4,
            targetNodeId:3,
        },
        {
            type: 'bezier',
            sourceNodeId: 5,
            targetNodeId:2,
          }, {
            type: 'bezier',
            sourceNodeId: 5,
            targetNodeId:4,
          }, {
            type: 'bezier',
            sourceNodeId: 5,
            targetNodeId:6,
          },
          {
            type: 'bezier',
            sourceNodeId: 5,
            targetNodeId:7,
          },{
            type: 'bezier',
            sourceNodeId: 7,
            targetNodeId:8,
          },
        ],
    }

    // 自定义矩形节点
    // class CustomNodeView extends RectNode {
    // }

    // class CustomNodeModel extends RectNodeModel {
    //     initNodeData(data) {
    //       super.initNodeData(data);
    //       this.width = 100;
    //       this.height = 40;
    //       this.radius = 3;
    //     }
    // }
    // const customRectNode = {
    //   type: "customNode",
    //   view: CustomNodeView,
    //   model: CustomNodeModel,
    // }
    // 自定义html节点
    class CustomHtmlNode extends HtmlNode {
      setHtml(rootEl) {
        const { properties } = this.props.model;
        const el = document.createElement('div');
        el.className = 'node-main';
        const html = `
          <div class="node-box">
            <div class="node-top"></div>
            <div class="node-bottom">
              <span class="node-keyId">${properties.keyId ? properties.keyId : ''}</span>
              <span class="node-keyData">${properties.keyData ? properties.keyData : ''}</span>
            </div>
          </div>`;
          el.innerHTML = html;
          rootEl.innerHTML = '';
          rootEl.appendChild(el);
          // window.stop = (ev) => {
          //   ev.stopPropagation();
          // };
          // window.setData = () => {
          //   const { graphModel, model } = this.props;
          //   graphModel.eventCenter.emit('custom:button-click', model);
          // };
        }
      }

    class CustomHtmlNodeModel extends HtmlNodeModel {
      setAttributes() {
        this.width = 140;
        this.height = 70;
        this.text.editable = true;
      }

      formatText(data) {
        data.text = {
          value: data.text.value || "",
          x: data.x,
          y: data.y - 10,
        };
      }
    }

    const autoHtmlNode = {
      type: 'htmlNode',
      view: CustomHtmlNode,
      model: CustomHtmlNodeModel,
    };
    lf.value.register(autoHtmlNode);
    lf.value.render(lfDataJs);
    // 单击选中节点获取节点数据
    lf.value.on('node:click,edge:click', (eventObject) => {
      if (eventObject.data.type === 'bezier') {
        edgeId.value = eventObject.data.id;
      } else {
        nodeId.value = eventObject.data.id;
        getNodeAtt(nodeId.value);
      }
    });
  }

  // 获取后端请求关系图数据
  const getLfNodeData = () => {
    // let timeNum = new Date().getTime();
    getLfData('2024-04-18 14:51:21').then(res => {
      // console.log(res)
      if (res.status === 200) {
        const nodes = [];
        const edges = [];
        for (let i = 0; i < res.data.nodes.length; i++) {
          nodes.push({
            id: res.data.nodes[i].id,
            type: res.data.nodes[i].type,
            x: res.data.nodes[i].x,
            y: res.data.nodes[i].y,
            text: {
              value: res.data.nodes[i].text
            },
            properties: {
              keyClass: res.data.nodes[i].properties ? res.data.nodes[i].properties.split(',')[0] : '',
              keyData: res.data.nodes[i].properties ? res.data.nodes[i].properties.split(',')[1] : '',
              keyId: res.data.nodes[i].properties ? res.data.nodes[i].properties.split(',')[2] : '',
              keyObj: res.data.nodes[i].properties ? res.data.nodes[i].properties.split(',')[3] : '',
            }
          })
        }
        for (let i = 0; i < res.data.edges.length; i++) {
          edges.push({
            type: res.data.edges[i].type,
            sourceNodeId: res.data.edges[i].sourceNodeId,
            targetNodeId: res.data.edges[i].targetNodeId,
          })
        }
        let data = {}
        data = {
          nodes: nodes,
          edges: edges
        }
        lf.value.clearData();
        lf.value.render(data);
      }
    }).catch(error => {
      console.log(error)
    });
  }
  // 添加新的关系图数据到后端
  const addLfNode = () => {
    const graphData = lf.value.getGraphData();
    const nodes = [];
    const edges = [];
    for (let i = 0; i < graphData.nodes.length; i++) {
      nodes.push({
        id: graphData.nodes[i].id,
        type: graphData.nodes[i].type,
        x: graphData.nodes[i].x,
        y: graphData.nodes[i].y,
        text: graphData.nodes[i].text.value,
        properties: graphData.nodes[i].properties.keyClass + ',' + graphData.nodes[i].properties.keyData + ',' + graphData.nodes[i].properties.keyId + ',' + graphData.nodes[i].properties.keyObj
      })
    }
    for (let i = 0; i < graphData.edges.length; i++) {
      edges.push({
        type: graphData.edges[i].type,
        sourceNodeId: graphData.edges[i].sourceNodeId,
        targetNodeId: graphData.edges[i].targetNodeId,
      })
    }
    let data = {}
    data = {
      nodes: nodes,
      edges: edges
    }

    addLfData(data).then(res => {
      if (res.status === 200) {
        console.log(res)
        message("添加成功", { type: "success" });
      }
    }).catch(error => {
      message(error.message, { type: "error" });
    });
  }

  // 画布以外的拖拽栏
  const dragNode = () => {
    lf.value.dnd.startDrag({
    type: 'htmlNode',
    text: '测试拖拽'
    })
  }
  // 撤销上一步
  const undoNodeEdge = () => {
  lf.value.undo();
  }
  // 基于边的id删除边
  const deleEdge = () => {
  lf.value.deleteEdge(edgeId.value)
  }
  // 下载流程图
  const downloadNode = () => {
    lf.value.getSnapshot();
  }
  // 获取流程图json数据
  const getGraphJson = () => {
    const graphData = lf.value.getGraphData();
  }
  // 删除节点
  const deleteNode = () => {
    lf.value.deleteNode(nodeId.value)
    lf.value.deleteEdge(edgeId.value)
  }
  // 修改节点文本值
  const editNodeText = (id,value) => {
    lf.value.updateText(id,value);
  }
  // 获取节点的所有上一级
  const nodeFather = () => {
    const nodeff = lf.value.getNodeIncomingNode(nodeId.value)
  }

  // 获取节点本身
  const getNodeModel = () => {
    console.log(lf.value.getNodeDataById(nodeId.value))
  }
  // 给选中节点添加工厂id自定义属性
  const setNodeKeyId = () => {
    time1.value = Math.random() * (0.5 - 0.1) + 0.1;
    time1.value = time1.value.toFixed(2);
    lf.value.setProperties(nodeId.value, {
      keyId: dataMap.value,
    });
  }
  // 给选中节点添加数据自定义属性
  const setNodeKeyData = () => {
     time2.value = Math.random() * (0.5 - 0.1) + 0.1;
    time2.value = time2.value.toFixed(2);
    keyData.value = '2000';
    lf.value.setProperties(nodeId.value, {
      keyData: keyData.value,
    });
  }
  // 给选中对象添加自定义属性
  const dataObjChange = (e) => {
    lf.value.setProperties(nodeId.value, {
      keyObj: e,
    });
  }
  // 给选中类别添加自定义属性
  const dataTypeChange = (e) => {
    lf.value.setProperties(nodeId.value, {
      keyClass: e,
    });
  }
  // 获取节点自定义属性
  const getNodeAtt = (id) => {
    const NodeData = lf.value.getProperties(id);
    dataMap.value = NodeData.keyId;
    keyData.value = NodeData.keyData;
    dataObj.value = NodeData.keyObj;
    dataType.value = NodeData.keyClass;
  }

  let fileRef = ref()
  let fileUp = ref();
  // 选择文件时被调用，将他赋值给fileRef
  const handleChange = (file,fileList) => {
    fileRef.value = file
    fileName.value = file.name;
    fileUp.value = file;
  }

  // 覆盖前一个选择的
  const handleExceed = (files) => {
    fileRef.value.clearFiles()
    const file = files[0];
    file.uid = genFileId()
    fileRef.value.handleStart(file)
  }

  // 下载xml文件
  const downloadXml = () => {
    const lfData = JSON.stringify(lf.value.getGraphData())
    download("logic-flow.xml", lfData);
  }
  // 下载文件
  const download = (filename, text) => {
    var element = document.createElement("a");
    element.setAttribute(
    "href",
    "data:text/plain;charset=utf-8," + encodeURIComponent(text)
    );
    element.setAttribute("download", filename);
    element.style.display = "none";
    document.body.appendChild(element);
    element.click();
    document.body.removeChild(element);
  }
  // 导入文件
  const uploadXml = (ev) => {
    const file = ev.target.files[0];
    const reader = new FileReader();
    reader.onload = (event) => {
      //console.log('-------event',event)
      if (event.target) {
        let data = event.target.result;
        lf.value.clearData();
        lf.value.render(JSON.parse(data));
      }
    };
    reader.readAsText(file);
    isShow.value = 1
    // this.dataObj = "0"
    // this.dataType = "1"
  }

  function handleFileUpload() {
    // 处理文件上传逻辑
    const inputElement = document.createElement("input");
    inputElement.type = "file";
    inputElement.accept = ".csv"; // 可以根据需要设置文件类型限制
    inputElement.onchange = event => {
      const selectedFile = event.target.files[0];
      if (selectedFile) {
        file.value = selectedFile.name;
        // 可以根据需要将文件信息存储在其他变量中
      }
    };
    inputElement.click();
  }
  function handleFileUpload1() {
    // 处理文件上传逻辑
    const inputElement = document.createElement("input");
    inputElement.type = "file";
    inputElement.accept = ".csv"; // 可以根据需要设置文件类型限制
    inputElement.onchange = event => {
      const selectedFile = event.target.files[0];
      if (selectedFile) {
        file.value = selectedFile.name;
        // 可以根据需要将文件信息存储在其他变量中
      }
    };
    inputElement.click();
  }
</script>

<style>
  .node-main {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    padding: 5px;
  }

  .node-box {
    box-sizing: border-box;
    width: 130px;
    height: 60px;
    background-color: #fff;
    border: 2px solid #e5e7eb;
    border-radius: 6px;
    box-shadow: 0px 6px 3px -2px rgba(0, 0, 0, 0.2);
  }

  .node-top {
    width: 100%;
    height: 30px;
    background-color: #fff;
    border-radius: 6px 6px 0 0;
  }

  .node-bottom {
    width: 100%;
    height: 30px;
    line-height: 30px;
    background-color: #e5e7eb;
    border-radius: 0 0 6px 6px;
    padding: 0 3px;
    font-size: 12px;
    display: flex;
    justify-content: space-between;
    overflow: hidden;
  }

  .node-keyId {
    flex: 1;
  }

  .node-keyData {
    flex: 1;
    text-align: right;
  }

  .up-input {
    width: 44px;
    height: 32px;
    position: absolute;
    left: 215px;
    top: 20px;
    z-index: 1000;
    opacity: 0;
  }
  .container-box {
    position: relative;
  }

  #container {
    width: 100%;
    height: 580px
    /*height: calc(100vh - 200px);*/
  }


  .lf-dndpanel {
    padding: 0;
    left: 500px;
    background-color: #c1c1c1;
  }

  .rectClass {
    width: 30px;
    height: 20px;
    border: #000 1px solid;
    border-radius: 4px;
    margin-top: 0;
  }

  .unClass {
    width: 16px;
    height: 16px;
  }
  .drag-class{
    width: 60px;
    height: 24px;
    margin-left: 20px;
    background-color: grey;
    margin-top: 15px;
    background-color: grey;
    border: 1px solid black; /* 添加黑色边框 */
    border-radius: 4px; /* 设置四边圆角 */

  }
  .drag-class::after {
  content: "添加";
  display: block; /* 让文本作为块级元素显示，从而实现在新行显示 */
  font-size: 14px; /* 设置文本字号 */
  color: white; /* 设置文本颜色 */
  text-align: center; /* 设置文本居中对齐 */
}
</style>

<style lang="scss" scoped>
.ontologyConstruction {
  width: 100%;
  height: calc(100vh - 200px);
  font-size: 16px;

  .grid-item {
    border-radius: 10px;
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
    background-color: #fff;
  }
  .question-mark {
    position: relative;
    display: inline-block;
    width: 20px;
    text-align: center;
    line-height: 20px;
    margin-left: 5px; /* 将右侧间距改为5px */
    font-size: 18px; /* 修改字体大小 */
  }

  .question-mark:hover::after {
    /* 使用 ::after 伪元素来显示文本 */
    content: " 使用本体实现资源数据的标准化描述及展示";
    position: absolute;
    top: -10px; /* 调整提示文本位置，使其位于问号的上方 */
    left: calc(100% + 5px); /* 设置文本距离问号图案的距离 */
    padding: 5px;
    background-color: #fff;
    color: #000;
    border: 1px solid #000;
    border-radius: 4px;
    display: block;
    max-width: 400px; /* 设置最大宽度 */
    white-space: nowrap; /* 防止文本换行 */
    word-wrap: break-word;
    font-size: 14px;
  }
  .question-mark1 {  position: relative;
    display: inline-block;
    width: 20px;
    text-align: center;
    line-height: 20px;
    margin-left: 5px; /* 将右侧间距改为5px */
    font-size: 18px;
  }

  .question-mark1:hover::after {
    /* 使用 ::after 伪元素来显示文本 */
    content: " 使用本体实现资源数据的标准化描述及展示";
    position: absolute;
    top: -10px; /* 调整提示文本位置，使其位于问号的上方 */
    left: calc(100% + 5px); /* 设置文本距离问号图案的距离 */
    padding: 5px;
    background-color: #fff;
    color: #000;
    border: 1px solid #000;
    border-radius: 4px;
    display: block;
    max-width: 400px; /* 设置最大宽度 */
    white-space: nowrap; /* 防止文本换行 */
    word-wrap: break-word;
    font-size: 14px;
  }
  .question-mark2 {  position: relative;
    display: inline-block;
    width: 20px;
    text-align: center;
    line-height: 20px;
    margin-left: 5px; /* 将右侧间距改为5px */
    font-size: 18px;
  }

  .question-mark2:hover::after {
    /* 使用 ::after 伪元素来显示文本 */
    content: " 使用本体实现资源数据的标准化描述及展示";
    position: absolute;
    top: -10px; /* 调整提示文本位置，使其位于问号的上方 */
    left: calc(100% + 5px); /* 设置文本距离问号图案的距离 */
    padding: 5px;
    background-color: #fff;
    color: #000;
    border: 1px solid #000;
    border-radius: 4px;
    display: block;
    max-width: 400px; /* 设置最大宽度 */
    white-space: nowrap; /* 防止文本换行 */
    word-wrap: break-word;
    font-size: 14px;
  }
  .question-mark3 {  position: relative;
    display: inline-block;
    width: 20px;
    text-align: center;
    line-height: 20px;
    margin-left: 5px; /* 将右侧间距改为5px */
    font-size: 18px;
  }

  .question-mark3:hover::after {
    /* 使用 ::after 伪元素来显示文本 */
    content: " 使用本体实现资源数据的标准化描述及展示";
    position: absolute;
    top: -10px; /* 调整提示文本位置，使其位于问号的上方 */
    left: calc(100% + 5px); /* 设置文本距离问号图案的距离 */
    padding: 5px;
    background-color: #fff;
    color: #000;
    border: 1px solid #000;
    border-radius: 4px;
    display: block;
    max-width: 400px; /* 设置最大宽度 */
    white-space: nowrap; /* 防止文本换行 */
    word-wrap: break-word;
    font-size: 14px;
  }
  .box1 {
    width: 100%;
    background-color: #f2f3f5;
    margin-top: 0px;
    overflow: auto; /* 启用滚动条 */


  }

  .header_1 {
    width: 100%;
    height: 30px;
    line-height: 30px;
    padding-left: 20px;
    border-bottom: 1px solid #ccc;
    margin-bottom: 20px;
  }
  .header_2 {
    width: 100%;
    height: 30px;
    line-height: 30px;
    padding-left: 20px;
    border-bottom: 1px solid #ccc;
    margin-bottom: 0px;
    display: flex;
    align-items: center
  }
  .delete-node {
    width: 36px;
    height: 24px;
    position: absolute;
    top: 4px;
    left: 0;
    margin-left: 490px;
    margin-top: 16px;
    background-color: #d2cfcf;
    display: flex;
    justify-content: center;
    cursor: pointer;
    align-items: center;
    border-radius: 4px;
    border: 1px solid #e7e9ed;
  }
  .undoEdge{
    width: 25px;
    height: 20px;
    background-color: #ccc;
    margin-left: 80px;
    margin-top: 14px;
    border-radius: 4px;
    border: 1px solid #e7e9ed;
  }
  .object,
  .classfication {
    width: calc(50% - 30px);
    margin-left: 20px;
    display: inline-block;
    vertical-align: top;
    margin-bottom: 20px;
  }
  .mapping {
    width: calc(100% - 42px);
    margin-left: 20px;
    display: inline-block;
    vertical-align: top;
    margin-bottom: 20px;
  }
  .object .title,
  .classfication .title,
  .mapping .title {
    display: block;
    padding-bottom: 10px;
  }

  .btns {
    width: calc(100% - 40px);
    margin-left: 20px;
    margin-top: 10px;
    margin-bottom: 20px;
  }

  .btns el-button {
    margin-right: 20px;
  }

  .input-with-select {
    max-width: calc(100% - 40px);
  }
  .file{
    width: 20px;
    height: 20px;
  }
}
</style>
